ELBとBlazeDSのストリーミング通信との相性
今回は担当したプロジェクトでAWSを使用したので、そこで知り得たことについて書いてみました。
■ELBとBlazeDSを使ったプロジェクト
担当したプロジェクトの当初の構成は、メッセージングにBlazeDS 4.0.1を使いEC2のオートスケールも必要となるものでした。
そこでELBを立てて、EC2をオートスケールさせ複数のEC2インスタンス間でBlazeDSをクラスタリングし、その中でメッセージングを行う構成を考えました。
アプリの性質上、多くのクライアントに頻繁にデータを送るケースが発生するので、なるべくコストをかけないようにBlazeDSの通信にはHTTPストリーミング(クライアント/サーバ間でコネクション繋ぎっぱなし)を採用しました。
ストリーミングの他にロングポーリングという選択肢もありましたが、ロングポーリングはサーバーがプッシュする都度、クライアントからポーリングリクエストを送るというコストが掛かるため、今回ケースでは見送りました。
ストリーミング通信の終了は、5秒間隔でサーバーからハートビートをクライアントに送信し、その応答により接続の有無を判定して不要なコネクションは切断するようにしています。
■前述の構成でELBを立てると、CloseWaitが残ってしまう!
コネクション切断の手順は、
ESTABLISHED→CLOSE WAIT→LAST ACK→CLOSED
ですが、ELBを通すとClose wait(ハーフクローズ)のままコネクションが残ってしまい、これを放置するとサーバースレッドも残り続け最悪全てのコネクションを塞いでしまうか、スレッドにメモリーを圧迫されサーバーがダウンしてしまう事になってしまいます。
不思議な事にEC2と直接通信を行うと正常にCLOSEできました。
■結局、原因は。。。
原因をいろいろと調査したのですが、なかなか解決策が見つからずELBをたてるとどうしてもClose waitが残ってしまいます。
どうやらELBとBlazeDSのストリーミング通信の組み合わせでClose waitが残ってしまうことを回避するのは無理なようです。
プロジェクト要件として多くのクライアントに頻繁にデータを送るケースが発生することと、高いレスポンス性能を求められていましたので、ELBは構成から外す事とし、オートスケールは今後の課題とすることにしました。